#include <stdio.h>
#include <time.h>
#ifdef MSDOS
#include <dos.h>
#else
#include "term.h"
#endif

#include "defines.h"

extern char	*p_buf, *prog;
extern char	*getlabel(), *gpop();
extern int	getval(), gettoken(), variables[];
extern int	tokentype, tokenstat;

/*
 * beep - sound terminal bell an optional number of times (default 1)
 */
void
b_beep(btoken)
char	*btoken;
{
	int	t = 1;

	tokentype = gettoken(btoken);		/* get optional argument */

	if (tokenstat != EOL && tokenstat != FINISHED) {
		if (tokentype == NUMBER)
			t = atoi(btoken);	/* numeric argument */
		else if (tokentype == VARIABLE)
			t = getval(btoken);
		else
			b_error(0);
	} else
		putback(btoken);

	/* do this at least once */
	do {
#ifdef MSDOS
		putchar('\07');			/* sound bell */
#else
		tputs(BL, 1, outchar);		/* sound bell */
#endif
	} while (--t > 0);
	return;
}


/*
 * b_sleep - suspend operation for optionally specified seconds (default 1)
 */
void
b_sleep(stok)
char	*stok;
{
	int	seconds = 1;
	long	time1, time2;

	tokentype = gettoken(stok);		/* get optional argument */

	if (tokenstat != EOL && tokenstat != FINISHED) {
		if (tokentype == NUMBER)
			seconds = atoi(stok);	/* numeric argument */
		else if (tokentype == VARIABLE)
			seconds = getval(stok);	/* variableargument */
		else
			b_error(0);
	} else
		putback(stok);

#ifdef MSDOS
	time (&time1);
	time2 = time1;
	while (difftime(time1, time2) < (double )seconds)
		time (&time1);
#else
	sleep (seconds);
#endif
	return;
}


/*
 * b_remark - eat lines beginning with "rem"
 */
void
b_remark()
{
	geteol();
	return;
}



/*
 * shell - emulate the BASIC shell statement
 */
void
b_shell(stok)
char	*stok;
{
	tokentype = gettoken(stok);		/* get shell argument */
	if (tokentype != QUOTE)
		b_error(0);			/* syntax error */
	else
		system (stok);
	return;
}


/*
 * b_cls - clear the screen.
 */
void
b_cls()
{
#ifdef MSDOS
	union REGS r;

	/* home cursor */
	r.h.ah = 2;		/* cursor addressing function */
	r.h.dl = 0;		/* column coordinate */
	r.h.dh = 0;		/* row coordinate */
	r.h.bh = 0;		/* video page */
	int86(0x10, &r, &r);

	/* get video attributes */
	r.h.ah = 8;		/* read character code */
	r.h.bh = 0;		/* page 0 */
	int86(0x10, &r, &r);
	r.h.bh = r.h.ah;	/* save attribute byte */

	/* clear screen */
	r.h.ah = 6;		/* screen scroll code */
	r.h.al = 0;		/* clear screen code */
	r.h.ch = 0;		/* start row */
	r.h.cl = 0;		/* start column */
	r.h.dh = 24;		/* end row */
	r.h.dl = 79;		/* end column */
	int86(0x10, &r, &r);
#else
	/* need to home the cursor */
	tputs(CL, LI, outchar);	/* clear the display */
#endif
	return;
}


/*
 * b_move - move cursor to x,y
 */
void
b_move(mtoken)
char	*mtoken;
{
#ifndef MSDOS
	char	outbuf[80];
#else
	union REGS r;
#endif
	int	x, y, rows, cols;

#ifdef MSDOS
	rows = 23;
	cols = 79;
#else
	rows = LI;
	cols = CO;
#endif
	tokentype = gettoken(mtoken);		/* get row number */

	if (tokentype == NUMBER) {
		x = atoi(mtoken);
	} else if (tokentype == VARIABLE)
		x = getval(mtoken);
	else
		b_error(0);

	tokentype = gettoken(mtoken);		/* get column number */

	if (tokentype == NUMBER) {
		y = atoi(mtoken);
	} else if (tokentype == VARIABLE)
		y = getval(mtoken);
	else
		b_error(0);

	if (x > rows || x < 0)			/* validate row */
		b_error(14);

	if (y > cols || y < 0)			/* validate column */
		b_error(15);

#ifndef MSDOS	/* THIS NEEDS TO BE TERMCAP!! (tgoto) */
	sprintf(outbuf, "\033[%d;%dH", x, y);
	tputs(outbuf, 1, outchar);
#else
	r.h.ah = 2;				/* cursor movement function */
	r.h.dl = y;				/* column coordinate */
	r.h.dh = x;				/* row coordinate */
	r.h.bh = 0;				/* video page */
	int86(0x10, &r, &r);
#endif
	return;
}


/*
 * b_goto - execute a GOTO statement
 */
void
b_goto(gtoken)
char	*gtoken;
{
	char	*loc;

	tokentype = gettoken(gtoken);		/* get label to go to */

	loc = getlabel(gtoken);			/* find the label location */

	if (loc == NULL)
		b_error(7);			/* label not defined */
	else
		prog = loc;			/* start program here */
	return;
}


/*
 * print - execute a simple version of the BASIC PRINT statement
 */
void
b_print(ptoken)
char	*ptoken;
{
	int	answer;
	int	len = 0, spaces;
	char	last_delim;

	do {
		tokentype = gettoken(ptoken);	/* get next list item */
		if (tokenstat == EOL || tokenstat == FINISHED)
			break;
		if (tokentype == QUOTE) {	/* is it a string */
			printf (ptoken);	/* beware of '%' in string */
			len += strlen(ptoken);	/* save string length */
			tokentype = gettoken(ptoken);/* get next token */
		} else {			/* or is it an expression? */
			putback(ptoken);	/* put expression back */
			getexp(ptoken, &answer);/* expand expression */
			tokentype = gettoken(ptoken);/* next token */
			len += printf ("%d", answer);
		}
		last_delim = *ptoken;		/* save last delimiter */

		if (*ptoken == ',') {		/* see if we new-line */
			/* compute number of spaces to move to next tab */
			spaces = 8 - (len % 8);
			len += spaces;		/* add the tabbing position */
			while (spaces) {
				printf (" ");
				spaces--;
			}
		} else if (*ptoken == ';')	/* do not advance cursor */
			;
		else if (tokenstat != EOL && tokenstat != FINISHED)
			b_error(0);
	} while (*ptoken == ';' || *ptoken == ',');

	if (tokenstat == EOL || tokenstat == FINISHED) {
		if (last_delim != ';' && last_delim != ',')
			printf ("\n");
	} else
		b_error(0);			/* error is not , or ; */
	return;
}


/*
 * input - execute a simple form of the BASIC INPUT command
 */
void
b_input(itoken)
char	*itoken;
{
	char	answer[80], var;
	int	i = 0;

	tokentype = gettoken(itoken);	/* see if prompt string is present */

	if (tokentype == QUOTE) {
		printf (itoken);	/* print it and check for comma */
		tokentype = gettoken(itoken);
		if (*itoken != ',')
			b_error(0);
		tokentype = gettoken(itoken);
	} else {			/* variable required */
		if (tokenstat == EOL || tokenstat == FINISHED)
			b_error(0);
		else
			printf ("? ");	/* otherwise, prompt with ? */
	}

	var = toupper(*itoken) - 'A';	/* get variable index */

	gets(answer);
	if (strlen(answer))		/* if nothing entered, */
		i = atoi(answer);
	else
		i = 0;			/* make it zero */
	variables[var] = i;		/* store value */
	return;
}


/*
 * b_gosub - execute a GOSUB command
 */
void
b_gosub(gtoken)
char	*gtoken;
{
	char	*loc;

	tokentype = gettoken(gtoken);
	loc = getlabel(gtoken);		/* find the label to call */
	if (loc == NULL)
		b_error(7);		/* label not defined */
	else {
		gpush(prog);		/* save place to return to */
		prog = loc;		/* start program at that location */
	}
	return;
}


/*
 * b_return - return from gosub
 */
void
b_return()
{
	prog = gpop();
	return;
}


/*
 * b_time - print system time
 */
void
b_time()
{
	long	t;
	struct	tm *b;

	time (&t);
	b = localtime(&t);
	printf("%02d:%02d:%02d", b->tm_hour,b->tm_hour,b->tm_sec);
	return;
}


/*
 * b_date - print system date
 */
void
b_date()
{
	long	t;
	struct	tm *b;

	time (&t);
	b = localtime(&t);
	printf("%02d/%02d/%02d", b->tm_mon,b->tm_mday,b->tm_year);
	return;
}


